package com.spring.framework.context;

import com.spring.framework.annotation.Component;
import com.spring.framework.annotation.ComponentScan;
import com.spring.framework.annotation.Scope;
import com.spring.framework.bean.BeanDefinition;
import com.spring.framework.exception.SpringException;
import com.spring.framework.factory.BeanFactory;
import com.spring.framework.utils.CollectionUtils;
import com.spring.framework.utils.ReflectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author xiaohei
 * @date 2021/12/1 15:42
 */
public class ApplicationContext {

    private static final Logger log = LoggerFactory.getLogger(ApplicationContext.class);

    private Class<?> clazz;

    private BeanFactory beanFactory;

    public ApplicationContext() {
    }

    public ApplicationContext(Class<?> clazz) {
        this.clazz = clazz;
    }

    public void run() {
        beanFactory = new BeanFactory();
        //扫描包文件
        //1.获取扫描路径
        ComponentScan componentScan = clazz.getAnnotation(ComponentScan.class);
        String basePackage = componentScan.value();
        Set<Class<?>> beanClassSet = null;
        try {
            beanClassSet = ReflectionUtil.getClasses(basePackage);
        } catch (IOException e) {
            log.error("获取class出现错误：", e);
        }
        if (CollectionUtils.isEmpty(beanClassSet)) {
            throw new SpringException("classSet is empty");
        }
        for (Class<?> clazz : beanClassSet) {
            if (clazz.isAnnotationPresent(Component.class)) {
                BeanDefinition bd = initBeanDefinition(clazz);
                beanFactory.registryBeanDefinition(bd.getBeanName(), bd);
            }
        }
        //将类注入进容器
        beanFactory.initBean();
    }

    public BeanDefinition initBeanDefinition(Class<?> clazz) {
        if (clazz == null) {
            throw new NullPointerException();
        }
        BeanDefinition bd = new BeanDefinition();
        String beanName = clazz.getName();
        bd.setBeanName(beanName);
        bd.setBeanClass(clazz);
        String scope = null;
        if (clazz.isAnnotationPresent(Scope.class)) {
            scope = clazz.getAnnotation(Scope.class).value();
        }else {
            scope = "singleton";
        }
        bd.setScope(scope);
        return bd;
    }

}
